package br.com.sadim.web;


import java.io.File;
import java.io.FileOutputStream;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.net.URL;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;


import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;

import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import javax.servlet.ServletContext;


import org.apache.axis.AxisFault;
import org.primefaces.event.FlowEvent;
import org.primefaces.model.DualListModel;



import br.com.drerp.financeiro.service.FinanceiroServiceImpl;
import br.com.drerp.financeiro.service.FinanceiroServiceImplServiceLocator;
import br.com.drerp.financeiro.service.FinanceiroServiceImplServiceSoapBindingStub;
import br.com.drerp.financeiro.service.NotaFiscal;
import br.com.drerp.financeiro.service.Pagador;
import br.com.drerp.financeiro.service.PlanoSaude;
import br.com.drerp.financeiro.service.Procedimento;
import br.com.drerp.financeiro.service.TipoProcedimento;
import br.com.sadim.diagnostico.Doenca;
import br.com.sadim.diagnostico.DoencaRN;
import br.com.sadim.diagnostico.Sintoma;
import br.com.sadim.diagnostico.SintomaRN;
import br.com.sadim.hospital.Consulta;
import br.com.sadim.hospital.ConsultaRN;
import br.com.sadim.hospital.Exame;
import br.com.sadim.hospital.ExameRN;
import br.com.sadim.hospital.HoraConsulta;
import br.com.sadim.hospital.NotaFiscalConsulta;
import br.com.sadim.hospital.NotaFiscalRN;
import br.com.sadim.hospital.ProcedimentoConsulta;
import br.com.sadim.hospital.ProcedimentoConsultaRN;
import br.com.sadim.hospital.Receituario;
import br.com.sadim.hospital.ReceituarioRN;
import br.com.sadim.hospital.StatusConsulta;
import br.com.sadim.hospital.TipoProcedimentoConsulta;


@ManagedBean(name="wizardConsultaBean")
@ViewScoped
public class WizardConsultaBean implements Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private Consulta consulta;
	private boolean finalizar = false;
	
	private boolean skip;
	
	
	private Exame exame1 = new Exame();
	private Exame exame2 = new Exame();  
	private Exame exame3 = new Exame(); 
	private Receituario receituario = new Receituario(); 

	private List<Receituario> receituarios = new ArrayList<Receituario>();

	private List<Exame> exames = new ArrayList<Exame>();

	//	private List<Doenca> selectedDoencas = new ArrayList<Doenca>();

	private DualListModel<Sintoma> sintomas;
	private DualListModel<Doenca> diagnosticosPossiveis;
	private DualListModel<ProcedimentoConsulta> procedimentos;
	
	private String newFileName;

	public void init() {       
		atribuirEstadoInicial();
	}

	private void atribuirEstadoInicial() {
		consulta = new Consulta();
	}


	public String salvar() {
		consulta.setSintomas(sintomas.getTarget());
		//Seta a hora do fim do atendimento
		consulta.setHoraAtendimento(new Date());
		if(finalizar) {
			consulta.setStatus(StatusConsulta.FINALIZADA);
			setFinalizar(false);
			consulta.setHoraFinalizada(new Date());
			
			
			//TODO Reponder ao service
			try {
				
				FinanceiroServiceImpl service = new FinanceiroServiceImplServiceSoapBindingStub(new URL("http://186.204.148.52:5574/Financeiro/services/FinanceiroServiceImplPort?wsdl"), new FinanceiroServiceImplServiceLocator());
				//FinanceiroServiceImpl service = new FinanceiroServiceImplServiceSoapBindingStub(new URL("http://172.23.151.170:8080/Financeiro2/services/FinanceiroServiceImplPort?wsdl"), new FinanceiroServiceImplServiceLocator());

				
				List<Procedimento> sux = new ArrayList<Procedimento>();
				Pagador pacientePagador = new Pagador();
				pacientePagador.setNome(consulta.getPaciente().getNome());
				pacientePagador.setDocumento(consulta.getPaciente().getCpf());
				
				//Procedimentos (materiais utilziados, etc)
				
				for(ProcedimentoConsulta pc : consulta.getProcedimento()) {
					Procedimento procedimento = new Procedimento();
					procedimento.setNome(pc.getNome());
					procedimento.setId(new Long(pc.getIdProcedimentoConsulta()));
					sux.add(procedimento);
					
				}
								
				//Tipo de consulta
				ProcedimentoConsultaRN prn = new ProcedimentoConsultaRN();
				ProcedimentoConsulta pc = prn.getByNome(consulta.getTipoConsulta());
				if(pc != null) {
					Procedimento tipoConsulta = new Procedimento();
					tipoConsulta.setNome(pc.getNome());
					tipoConsulta.setTipo(TipoProcedimento.PROCEDIMENTO);
					tipoConsulta.setId(new Long(pc.getIdProcedimentoConsulta()));
	
					sux.add(tipoConsulta);
				}
				if(consulta.getConvenio().equals("Particular")) {
					//TODO NotaFiscal
					NotaFiscal nf = service.pagarConsultaParticular(pacientePagador, sux.toArray(new Procedimento[sux.size()]));
					//Persisto no nosso banco
					NotaFiscalConsulta nfc = new NotaFiscalConsulta();
					nfc.setDescontos(nf.getDescontos());
					nfc.setValor(nf.getValor());
					NotaFiscalRN nfRN = new NotaFiscalRN();
					nfRN.salvar(nfc);
					
					consulta.setNotaFiscal(nfc);
					
				} else {
					PlanoSaude ps = new PlanoSaude();
					Long planoSaudeId = new Long("0");
					for(PlanoSaude plano : service.listarPlanosSaude()){
						if(plano.getNome().equals(consulta.getConvenio()))
							planoSaudeId = plano.getId();
					}
					ps.setNome(consulta.getConvenio());
					ps.setId(planoSaudeId);
					System.out.println(service.pagarConsultaPlanoSaude(ps, sux.toArray(new Procedimento[sux.size()])));
					
				}
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			
			
		}
		receituarios.add(receituario);
		exames.add(exame1);
		exames.add(exame2);
		exames.add(exame3);	
		consulta.setExame(exames);
		consulta.setReceituario(receituarios);
		consulta.setDiagnosticos(diagnosticosPossiveis.getTarget());
		
		consulta.setProcedimento(procedimentos.getTarget());
		
		ConsultaRN consultaRN = new ConsultaRN();
		ExameRN exameRN = new ExameRN();
		ReceituarioRN receituarioRN = new ReceituarioRN();

		receituarioRN.salvar(receituario);
		exameRN.salvar(exame1);
		exameRN.salvar(exame2);
		exameRN.salvar(exame3);
		consultaRN.salvar(consulta);
		
		//Deleta o arquivo temporario de foto
		ServletContext servletContext = (ServletContext) FacesContext.getCurrentInstance().getExternalContext().getContext();  
        newFileName = servletContext.getRealPath("") + File.separator + "foto" + ".png";  
		File f = new File(newFileName);
        f.delete();
        
        FacesContext context = FacesContext.getCurrentInstance();
		context.addMessage(null, new FacesMessage("Dados cadastrados com sucesso"));
		return "listagemConsulta";
	}
	


	public boolean isFinalizar() {  
		return finalizar;  
	}  

	public void setFinalizar(boolean finalizar) {  
		this.finalizar = finalizar;  
	}  

	public String onFlowProcess(FlowEvent event) {
		gerarDiagnosticos();
		if(finalizar) {
			System.out.println("AFF");
		}
		

			return event.getNewStep();
	}

	public Consulta getConsulta() {
		return consulta;
	}

	public void setConsulta(Consulta consulta) {
		this.consulta = consulta;
		inicializa();
	}

	private void inicializa() {
		List<Sintoma> source  = new ArrayList<Sintoma>();
		List<Sintoma> target  = new ArrayList<Sintoma>();

		List<Doenca> sourceD  = new ArrayList<Doenca>();
		List<Doenca> targetD = new ArrayList<Doenca>();
		
		List<ProcedimentoConsulta> sourceP  = new ArrayList<ProcedimentoConsulta>();
		List<ProcedimentoConsulta> targetP = new ArrayList<ProcedimentoConsulta>();
		SintomaRN sintomaRN = new SintomaRN();
		ProcedimentoConsultaRN procedimentoConsultaRN = new ProcedimentoConsultaRN();
		if(this.consulta != null) {
			target = new ArrayList<Sintoma>(consulta.getSintomas());
			targetD =  new ArrayList<Doenca>(consulta.getDiagnosticos());
			
			targetP = new ArrayList<ProcedimentoConsulta>(consulta.getProcedimento());
			exames = new ArrayList<Exame>(consulta.getExame());
			if(exames.size() >= 3) {
				exame3 = exames.get(2);
			}
			if(exames.size() >= 2) {
				exame2 = exames.get(1);
			}
			if(exames.size() >= 1) {
				exame1 = exames.get(0);
			}
			receituarios = new ArrayList<Receituario>(consulta.getReceituario());
			if(receituarios.size() >= 1) {
				receituario = receituarios.get(0);
			}
		}
		List<ProcedimentoConsulta> listaP = new ArrayList<ProcedimentoConsulta>();
		
		for(ProcedimentoConsulta pc : procedimentoConsultaRN.getList()) {
			if(!pc.getTipo().equals(TipoProcedimentoConsulta.PROCEDIMENTO)) {
				listaP.add(pc);
			}
		}
		
		source = junta(sintomaRN.getList(), target);
		sourceP = junta(listaP, targetP);

		
		diagnosticosPossiveis = new DualListModel<Doenca>(sourceD, targetD);
		sintomas = new DualListModel<Sintoma>(source, target);
		procedimentos = new DualListModel<ProcedimentoConsulta>(sourceP, targetP);
	}

	public DualListModel<Sintoma> getSintomas() {
		return sintomas;
	}

	public void setSintomas(DualListModel<Sintoma> sintomas) {
		this.sintomas = sintomas;
	}

	public List<Exame> getExames() {
		return exames;
	}

	public void setExames(List<Exame> exames) {
		this.exames = exames;
	}

	/*
	 * @return: lista1 - lista2
	 */
	public static <T> List<T> junta(List<T> lista1, List<T> lista2) {  
		List<T> lista3 = new ArrayList<T>();  
		lista3.addAll(lista1);  
		lista3.addAll(lista2);  
		T elemento = null;
		for (int i = 0; i < lista3.size(); i++) {  
			elemento = lista3.get(i);  
			if (lista1.contains(elemento) && lista2.contains(elemento)) {  
				lista3.remove(i);  
				i--;  
			}  
		}  
		return lista3;  
	}

	public Exame getExame1() {
		return exame1;
	}

	public void setExame1(Exame exame1) {
		this.exame1 = exame1;
	}

	public Exame getExame2() {
		return exame2;
	}

	public void setExame2(Exame exame2) {
		this.exame2 = exame2;
	}

	public Exame getExame3() {
		return exame3;
	}

	public void setExame3(Exame exame3) {
		this.exame3 = exame3;
	}

	public void gerarDiagnosticos() {
		List<Doenca> listaDoencas = new ArrayList<Doenca>();
		DoencaRN doencaRN = new DoencaRN();
		for(Sintoma s : sintomas.getTarget()) {
			for(Doenca d : doencaRN.getBySintoma(s.getIdSintoma())) {
				if(!listaDoencas.contains(d))
					listaDoencas.add(d);
			}
		}
		diagnosticosPossiveis.setSource(junta(listaDoencas, diagnosticosPossiveis.getTarget()));
	}

	public DualListModel<Doenca> getDiagnosticosPossiveis() {
		return diagnosticosPossiveis;
	}

	public void setDiagnosticosPossiveis(DualListModel<Doenca> diagnosticosPossiveis) {
		this.diagnosticosPossiveis = diagnosticosPossiveis;
	}


	public List<SelectItem> getListHorasConsulta() {
		List<SelectItem> tipos = new ArrayList<SelectItem>();  

		for (HoraConsulta h : HoraConsulta.values()) {  
			tipos.add(new SelectItem(h, h.getTipo()));  
		}  

		return tipos;	
	}

	public Receituario getReceituario() {
		return receituario;
	}

	public void setReceituario(Receituario receituario) {
		this.receituario = receituario;
	}
	
	public String editar() {
        try{
        	ServletContext servletContext = (ServletContext) FacesContext.getCurrentInstance().getExternalContext().getContext();  
            newFileName = servletContext.getRealPath("") + File.separator + "foto" + ".png";  
            FileOutputStream fos = new FileOutputStream(newFileName);
            fos.write(consulta.getPaciente().getFoto());
            fos.close();
        }catch(Exception e){
            e.printStackTrace();
        }
        if(!consulta.getStatus().equals(StatusConsulta.OCORRENDO)) {
        	consulta.setHoraAtendimento(new Date());
        	consulta.setStatus(StatusConsulta.OCORRENDO);
        }
		
		ConsultaRN consultaRN = new ConsultaRN();
		consultaRN.salvar(consulta);
		return "consulta?faces-redirect=true&amp;includeViewParams=true";
	}

	public boolean isSkip() {
		return skip;
	}

	public void setSkip(boolean skip) {
		this.skip = skip;
	}

	public String getNewFileName() {
		return newFileName;
	}

	public void setNewFileName(String newFileName) {
		this.newFileName = newFileName;
	}

	public DualListModel<ProcedimentoConsulta> getProcedimentos() {
		return procedimentos;
	}

	public void setProcedimentos(DualListModel<ProcedimentoConsulta> procedimentos) {
		this.procedimentos = procedimentos;
	}

}
